AWS Lambda Web AdapterとFastAPIで作る!Amazon BedrockのストリームAPIを使ったチャットアプリ

AWS Lambda Web AdapterとFastAPIで作る!Amazon BedrockのストリームAPIを使ったチャットアプリ

ウェブアプリをLambda関数化できるAWS Lambda Web Adapterを使ってみた
Clock Icon2024.11.18

生成AIのストリームAPIを活用したアプリケーション開発の機会が増えています。

  • フロントエンドはAPIを動作確認できれば良い
  • 当面(開発中)はランニングコストを抑えたい
  • 将来的なECSへの実行基盤の移行に対して、改修コストを抑えたい

このような要件に対して、AWS Lambda Web Adapterを使ってSPAなウェブアプリケーションをLambda関数として動作させる方法を紹介します。

serverless-storyteller-architecture

※ 引用元 https://github.com/awslabs/aws-lambda-web-adapter/blob/main/examples/fastapi-response-streaming/imgs/serverless-storyteller-architecture.png

本記事では、サーバーサイドフレームワークにFastAPI、ストリームAPIにAmazon BedrockのInvokeModelWithResponseStream API、基盤モデルにClaude 3 Haikuを利用します。

動作確認は、以下の2ステップで行います。

  1. uvで環境構築してローカルで動作確認
  2. AWS SAMを使い、Lambda Function URLとAWS Lambda Web Adapterを組み合わせてLambda単体でアプリケーションを動作確認

以下のGitHubレポジトリで公開されているアプリで動作確認します

https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/fastapi-response-streaming

事前にレポジトリを clone しておきましょう。

$ git clone https://github.com/awslabs/aws-lambda-web-adapter.git
$ cd aws-lambda-web-adapter/examples/fastapi-response-streaming
$ tree .
.
├── README.md
├── app
│   ├── Dockerfile
│   ├── main.py
│   ├── requirements.txt
│   └── static
│       ├── index.html
│       ├── script.js
│       └── style.css
├── imgs
│   ├── demo.gif
│   └── serverless-storyteller-architecture.png
└── template.yaml

Amazon Bedrock の基盤モデルを有効化

基盤モデルとしてAnthropicのClaude 3 Haikuを利用します。まだ、モデルの利用申請を行っていない場合は、利用するリージョンで申請を済ませておきましょう。

モデルが利用可能でない場合は、以下のようなエラーが発生します

botocore.errorfactory.AccessDeniedException: An error occurred (AccessDeniedException) when calling the InvokeModelWithResponseStream operation: You don't have access to the model with the specified model ID.

ローカル環境でチャットアプリを動作させる

FastAPIのPythonランタイムとパッケージの管理には uv を利用します。

次のドキュメントに従い、uv をあらかじめインストールしておいてください

https://docs.astral.sh/uv/getting-started/installation/

本記事では、 uv 0.5.2 で動作確認しました。

$ brew install uv
$ uv --version
uv 0.5.2 (Homebrew 2024-11-14)

繰り返しとなりますが、GitHubにある aws-lambda-web-adapter を clone し、サンプルアプリケーションのあるディレクトリに移動します。

$ git clone https://github.com/awslabs/aws-lambda-web-adapter.git
$ cd aws-lambda-web-adapter/examples/fastapi-response-streaming

後半のステップでは Python 3.12 ランタイムのLambdaを利用するため、ローカル環境でも同じバージョンを利用します。

$ uv init --app --python 3.12
Initialized project `fastapi-response-streaming`

$ uv add -r app/requirements.txt
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: .venv
...
 + uvicorn==0.23.2
$ cd app/
$ uv run main.py
INFO:     Started server process [18764]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)

INFO:     1.2.3.4:2809 - "POST /api/story HTTP/1.1" 200 OK

上記コマンド実行後、ブラウザから http://localhost:8080/ にアクセスしましょう。

チャット画面が表示されます。

キーワードを入力すると、ねんねんころりな話しを創作してくれます。

fastapi-bedrock-chat-demo

AWS API との bedrock.invoke_model_with_response_stream のストリームイベントを yield し、FastAPI のレスポンスとしては fastapi.responses.StreamingResponse でラップします。

AWS Lambda環境でチャットアプリを動作させる

AWS Lambda Web Adapterは、WebアプリケーションとAWS Lambdaインターフェースのギャップを埋めるLambda Extensionです。
このツールを利用することで、Lambda向けにハンドラーやレスポンスを実装することなく、WebアプリケーションをそのままLambda関数として実行できるようになります。

AWS Lambda Web Adapterを使い、WebアプリケーションをLambda関数で動作させる決まり事は2つです

  • Webアプリケーションを 8080 ポートで起動
  • AWS Lambda Web Adapterを /opt/extensions 以下で実行

たったこれだけです。

先ほどのアプリケーションをコンテナLambdaとしてDockerfileで定義したのが以下です。

FROM public.ecr.aws/docker/library/python:3.12.0-slim-bullseye
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter

WORKDIR /app
ADD . .
RUN pip install -r requirements.txt

CMD ["python", "main.py"]

Dockerfile 2行目の COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter が AWS Lambda Web Adapter 固有の対応です。

AWS LambdaにはLambda Function URLという機能があり、Lambda関数をパブリックなURLで公開することができます。

AWS Lambda Web AdapterとLambda Function URLを組み合わせることで、Lambdaを実行基盤にWebアプリケーションを簡単に公開できます。

AWS Serverless Application Model(AWS SAM) を使うと、このような構成を簡単にデプロイできます。

$ sam build
$ sam deploy --guided

次のドキュメントに従い、AWS SAM CLI をあらかじめインストールしておいてください

https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html

内部的には、以下のテンプレートを利用してIaC化してデプロイされています。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  Streaming Bedrock Response with FastAPI on AWS Lambda

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 300

Resources:
  FastAPIFunction:
    Type: AWS::Serverless::Function
    Properties:
      PackageType: Image
      MemorySize: 512
      Environment:
        Variables:
          AWS_LWA_INVOKE_MODE: RESPONSE_STREAM
      FunctionUrlConfig:
        AuthType: NONE
        InvokeMode: RESPONSE_STREAM
      Policies:
      - Statement:
        - Sid: BedrockInvokePolicy
          Effect: Allow
          Action:
          - bedrock:InvokeModelWithResponseStream
          Resource: '*'
      Tracing: Active
    Metadata:
      Dockerfile: Dockerfile
      DockerContext: ./app
      DockerTag: v1

Outputs:
  FastAPIFunctionUrl:
    Description: "Function URL for FastAPI function"
    Value: !GetAtt FastAPIFunctionUrl.FunctionUrl
  FastAPIFunction:
    Description: "FastAPI Lambda Function ARN"
    Value: !GetAtt FastAPIFunction.Arn

AWS Lambda Web Adapterは何が嬉しい?

AWS Lambda Web Adapterツールを使ってWebアプリをLambda関数として実行する大きなメリットとして次の2点があります。

  • WebアプリケーションをLambda向けにカスタマイズすることなく、そのままLambda関数として実行できる
  • Lambda関数は、本記事で紹介したFunction URL以外にも、API GatewayやALB経由などでも呼び出せる

lambda-adapter-overview

※ 画像引用元 https://github.com/awslabs/aws-lambda-web-adapter/blob/main/docs/images/lambda-adapter-overview.png

Function URLとして公開されたLambda関数は、CloudFrontとも容易に連携できます。

https://dev.classmethod.jp/articles/integrate-aws-lambda-with-cloudfront/

AWS Lambda Web Adapterを使ってWebアプリケーションをLambda関数として実行できるようにすることで、柔軟なサーバーレス構成を構築できます。

ローカル開発したものをLambdaに持っていったり、ALB配下でLambdaを動作させると、そこからさらにECSへシームレスに移行できます。

PoCのような検証時や社内ツールの簡易的な実行基盤としても非常に重宝できます。

GitHubのaws-lambda-web-adapterレポジトリの examples ディレクトリ配下には、今回紹介したFastAPI以外にも、Next.jsやSpring Bootなど人気フレームワークのサンプルコードが豊富に用意されています。

各サンプルはAWS SAMで簡単に実行できるので、ぜひ一度お試しください。

参考

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.